<?php
namespace app\common\validate;

use think\Validate;

/**
 * 自定义验证类的基类（自定义一些常用的验证规则，便于子类的快速验证）
 *
 * @author LCY <409028735@qq.com>
 */
class Base extends Validate
{
    /**
     * @var string
     * 主键字段名称，主要应用于删除的验证
     */
    protected $primary_key = 'id';

    /**
     * 定义通用的删除场景验证
     * @return Base
     * Author: LCY<409028735@qq.com>
     * Time: 2021/11/29 14:59
     * Note:按主键进行删除
     */
    public function sceneDelete(){
        return $this->only([ $this->primary_key ]);
    }


    /*****************************以下五为自定义验证规则，便于后续的验证******************************/

    /**
     * 自定义日期检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 用该验证方法可以替代官方的多个日期的验证规则
     */
    public function checkDate($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m-d';

        //检测是否符合正确的日期要求
        if(true !== $this->is($value, 'date')){
            return false;
        }

        //检测日期的格式是否正确
        if(true !== $this->dateFormat($value, $rule)){
            return false;
        }

        //进一步检测日期的格式
        if(date($rule, strtotime($value)) != $value){
            return false;
        }

        return true;
    }

    /**
     * 自定义时间检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 验证的格式固定是例如：12:05:05
     */
    public function checkTime($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'H:i:s';

        //进一步检测时间的格式
        if(date($rule, strtotime($value)) != $value){
            return false;
        }

        return true;
    }

    /**
     * 自定义日期时间检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note:
     */
    public function checkDateTime($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m-d H:i:s';
        //检测是否符合正确的日期要求
        if(true !== $this->is($value, 'date')){
            return false;
        }

        //进一步检测日期的格式
        if(date($rule, strtotime($value)) != $value){
            return false;
        }

        return true;
    }

    /**
     * 自定义多个日期检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 多个日期用英文逗号分割
     */
    public function checkMultiDate($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m-d';
        $dates = explode(',', $value);

        if(empty($dates) || !is_array($dates)){
            return false;
        }

        //逐一检测单个日期是否正确
        foreach ($dates as $date){
            if(true !== $this->checkDate($date,$rule)){
                return false;
            }
        }

        return true;
    }

    /**
     * 自定义日期区间检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 用该验证方法可以替代官方的多个日期的验证规则
     */
    public function checkDateRange($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m-d';

        $delimiter = ' - ';//日期区间的分隔符
        if(!strpos($value, $delimiter)){
            return false;
        }

        list($before_date, $after_date) = explode($delimiter, $value);

        //检测是否符合正确的日期要求
        if(true !== $this->checkDate($before_date, $rule, $data)){
            return false;
        }

        if(true !== $this->checkDate($after_date, $rule, $data)){
            return false;
        }

        //比较日期的大小
        if(strtotime($before_date) > strtotime($after_date)){
            return false;
        }

        return true;
    }

    /**
     * 自定义日期区间检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 用该验证方法可以替代官方的多个日期的验证规则
     */
    public function checkDateTimeRange($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m-d H:i:s';

        $delimiter = ' - ';//日期区间的分隔符
        if(!strpos($value, $delimiter)){
            return false;
        }

        list($before_date, $after_date) = explode($delimiter, $value);

        //检测是否符合正确的日期要求
        if(true !== $this->checkDatetime($before_date, $rule, $data)){
            return false;
        }

        if(true !== $this->checkDatetime($after_date, $rule, $data)){
            return false;
        }

        //比较日期的大小
        if(strtotime($before_date) > strtotime($after_date)){
            return false;
        }

        return true;
    }

    /**
     * 自定义月份检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 格式：01或12，都是两个数字
     */
    public function checkMonth($value, $rule = '', $data = [])
    {
        if(!preg_match('/^0[1-9]|1[0-2]$/', $value)){
            return false;
        }

        return true;
    }

    /**
     * 自定义年月份检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 格式：2020-01
     */
    public function checkYearMonth($value, $rule = '', $data = [])
    {
        $rule = $rule ?: 'Y-m';

        //检测日期的格式是否正确
        if(true !== $this->dateFormat($value, $rule)){
            return false;
        }

        //进一步检测日期的格式
        if(date($rule, strtotime($value)) != $value){
            return false;
        }

        return true;
    }

    /**
     * 自定义颜色检测
     * @param string $value   验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 格式： 1：#rrggbb  2：rgb(r,g,b)  3：rgba(r,g,b,p)
     */
    public function checkColor($value, $rule = '', $data = [])
    {
        $rules = [
            1 => '^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$',
            2 => '^[rR][gG][Bb][Aa]?[\(]((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),){2}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?(0\.\d{1,2}|1|0)?[\)]{1}$'
        ];

        foreach ($rules as $rule){
            if(preg_match('/'.$rule.'/', $value)){
                return true;
            }
        }

        return false;
    }

    /**
     * 自定义登录用户名检测
     * @param string $value  验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 格式： 由数字、字母、下划线(一种多多种组成，且只能字母开头)，只验证格式，不验证长度
     */
    public function checkUsername($value, $rule = '', $data = [])
    {
        if(!preg_match('/^[A-Za-z][A-Za-z0-9\_]+$/', $value)){
            return false;
        }

        return true;
    }

    /**
     * 自定义登录密码检测
     * @param string $value  验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 格式： 由数字、字母、下划线、特殊符号!@#$%^&*()_+(一种多多种组成)，只验证格式，不验证长度
     */
    public function checkPassword($value, $rule = '', $data = [])
    {
        if(!preg_match('/^[\S]+$/', $value)){
            return false;
        }

        return true;
    }

    /**
     * 自定义小数检测
     * @param string $value  验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 可以检测整数和小数，主要是便于验证金额等小数,rule中可以传入小数点前几位和小数点后几位，用英文逗号分隔，不允许小数点结尾的值
     */
    public function checkFloat($value, $rule = '', $data = [])
    {
        $prefix_length = 8;//小数点前位数
        $postfix_length = 2;//小数点后位数

        if(!empty($rule) && is_string($rule) && strpos($rule, ',')){
            list($prefix_length, $postfix_length) = explode(',', $rule);
        }

        //没有小数的情况
        $regx = '/^-?(0|[1-9][0-9]{0,'.($prefix_length-1).'})$/';

        if($postfix_length >= 1){
            //有小数的情况
            $regx = '/^-?(0|[1-9][0-9]{0,'.($prefix_length-1).'})(\.[0-9]{1,'.$postfix_length.'})?$/';
        }

        if(!preg_match($regx, $value)){
            return false;
        }

        return true;
    }

    /**
     * 自定义多个ID检测
     * @param string $value  验证的值
     * @param string $rule   验证规则
     * @param array $data    全部数据
     * @return bool|string
     * Author: LCY<409028735@qq.com>
     * Time: 2020/11/25 11:33
     * Note: 数组形式 或 多个id用英文逗号分隔，例如：1,2,3，可应用于批量操作的场景
     */
    public function checkIds($value, $rule = '', $data = [])
    {
        if(is_string($value)){
            $value = explode(',', $value);
        }
        foreach ($value as $v){
            if(!is_numeric($v)){
                return false;
            }

            $val = 0 + $v;
            if(!is_int($val) || $val < 0){
                return false;
            }
        }

        return true;
    }

}